(ns util.contrib.java-utils
  (:use clojure.java.io)
  (:import java.io.File
           java.util.Properties))


(defn as-str
  "Like clojure.core/str, but if an argument is a keyword or symbol,
  its name will be used instead of its literal representation.

  Example:
     (str :foo :bar)     ;;=> \":foo:bar\"
     (as-str :foo :bar)  ;;=> \"foobar\"

  Note that this does not apply to keywords or symbols nested within
  data structures; they will be rendered as with str.

  Example:
     (str {:foo :bar})     ;;=> \"{:foo :bar}\"
     (as-str {:foo :bar})  ;;=> \"{:foo :bar}\" "
  {:deprecated "1.2"}
  ([] "")
  ([x] (if (instance? clojure.lang.Named x)
         (name x)
         (str x)))
  ([x & ys]
    ((fn [^StringBuilder sb more]
       (if more
         (recur (. sb  (append (as-str (first more)))) (next more))
         (str sb)))
      (new StringBuilder ^String (as-str x)) ys)))

(defn get-system-property
  "Get a system property."
  ([stringable]
    (System/getProperty (as-str stringable)))
  ([stringable default]
    (System/getProperty (as-str stringable) default)))

; Not there is no corresponding props->map. Just destructure!
(defn ^Properties as-properties
  "Convert any seq of pairs to a java.utils.Properties instance.
   Uses as-str to convert both keys and values into strings."
  {:tag Properties}
  [m]
  (let [p (Properties.)]
    (doseq [[k v] m]
      (.setProperty p (as-str k) (as-str v)))
    p))

(defn read-properties
  "Read properties from file-able."
  [file-able]
  (with-open [f (java.io.FileInputStream. (file file-able))]
    (doto (Properties.)
      (.load f))))


